﻿using System;
using System.ServiceModel;
using System.ServiceModel.Channels;

namespace Tibco.ServiceModel
{
    internal abstract class TibcoReplyChannelBase : TibcoChannelBase, IReplyChannel, IChannel, ICommunicationObject
    {
        private readonly EndpointAddress _localAddress;

        private readonly Func<TimeSpan, RequestContext> _receiveMethod;

        private readonly CommunicationOperation<bool, RequestContext> _tryReceiveMethod;

        private readonly Func<TimeSpan, bool> _waitForMessage;

        public EndpointAddress LocalAddress
        {
            get
            {
                return this._localAddress;
            }
        }

        public EndpointAddress RemoteAddress => throw new NotImplementedException();

        public Uri Via => throw new NotImplementedException();

        protected TibcoReplyChannelBase(BindingContext context, EndpointAddress localAddress) : base(context)
        {
            this._localAddress = localAddress;
            TibcoReplyChannelBase TibcoInputChannelBase = this;
            this._receiveMethod = new Func<TimeSpan, RequestContext>(TibcoInputChannelBase.ReceiveRequest);
            TibcoReplyChannelBase TibcoInputChannelBase1 = this;
            this._tryReceiveMethod = new CommunicationOperation<bool, RequestContext>(TibcoInputChannelBase1.TryReceiveRequest);
            TibcoReplyChannelBase TibcoInputChannelBase2 = this;
            this._waitForMessage = new Func<TimeSpan, bool>(TibcoInputChannelBase2.WaitForRequest);
        }
        public virtual RequestContext ReceiveRequest()
        {
            return this.ReceiveRequest(base.Context.Binding.ReceiveTimeout);
        }

        public abstract RequestContext ReceiveRequest(TimeSpan timeout);

        public virtual IAsyncResult BeginReceiveRequest(AsyncCallback callback, object state)
        {
            return this._receiveMethod.BeginInvoke(base.Context.Binding.ReceiveTimeout, callback, state);
        }

        public virtual IAsyncResult BeginReceiveRequest(TimeSpan timeout, AsyncCallback callback, object state)
        {
            return this._receiveMethod.BeginInvoke(timeout, callback, state);
        }

        public RequestContext EndReceiveRequest(IAsyncResult result)
        {
            return this._receiveMethod.EndInvoke(result);
        }

        public abstract bool TryReceiveRequest(TimeSpan timeout, out RequestContext context);

        public virtual IAsyncResult BeginTryReceiveRequest(TimeSpan timeout, AsyncCallback callback, object state)
        {
            RequestContext requestContext;
            return this._tryReceiveMethod.BeginInvoke(timeout, out requestContext, callback, state);
        }

        public virtual bool EndTryReceiveRequest(IAsyncResult result, out RequestContext context)
        {
            return this._tryReceiveMethod.EndInvoke(out context, result);
        }

        public abstract bool WaitForRequest(TimeSpan timeout);

        public virtual IAsyncResult BeginWaitForRequest(TimeSpan timeout, AsyncCallback callback, object state)
        {
            return this._waitForMessage.BeginInvoke(timeout, callback, state);
        }

        public abstract bool EndWaitForRequest(IAsyncResult result);
    }
}